{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": "<tf.Tensor: shape=(5,), dtype=int32, numpy=array([ 0,  1,  4,  9, 16])>"
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import tensorflow as tf\n",
    "from tensorflow.keras import layers,models,regularizers\n",
    "\n",
    "mypower = layers.Lambda(lambda x: tf.math.pow(x,2))\n",
    "mypower(tf.range(5))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "outputs": [],
   "source": [
    "class Linear(layers.Layer):\n",
    "    def __init__(self,units=32,**kwargs):\n",
    "        super(Linear,self).__init__(**kwargs)\n",
    "        self.units = units\n",
    "\n",
    "    def build(self,input_shape):\n",
    "        self.w = self.add_weight(shape=(input_shape[-1],self.units),\n",
    "                                 initializer='random_normal',\n",
    "                                 trainable=True)\n",
    "        self.b = self.add_weight(shape=(self.units,),\n",
    "                                 initializer='random_normal',\n",
    "                                 trainable=True)\n",
    "        super(Linear,self).build(input_shape)\n",
    "\n",
    "\n",
    "    def call(self,inputs):\n",
    "        return tf.matmul(inputs,self.w) + self.b\n",
    "\n",
    "    def get_config(self):\n",
    "        config = super(Linear,self).get_config()\n",
    "        config.update({'units':self.units})\n",
    "        return config\n",
    "\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "linear = Linear(units=8)\n",
    "print(linear.built)\n",
    "\n",
    "linear.build(input_shape=(None,16))\n",
    "print(linear.built)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False\n",
      "(None, 8)\n"
     ]
    }
   ],
   "source": [
    "linear = Linear(units=8)\n",
    "print(linear.built)\n",
    "linear.build(input_shape=(None,16))\n",
    "print(linear.compute_output_shape(input_shape=(None,16)))"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False\n",
      "True\n",
      "{'name': 'linear_2', 'trainable': True, 'dtype': 'float32', 'units': 16}\n"
     ]
    }
   ],
   "source": [
    "linear = Linear(units=16)\n",
    "print(linear.built)\n",
    "#如果built = False，调用__call__时会先调用build方法, 再调用call方法。\n",
    "linear(tf.random.uniform((100,64)))\n",
    "print(linear.built)\n",
    "config = linear.get_config()\n",
    "print(config)\n",
    "\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "model.input_shape: (None, 64)\n",
      "model.output_shape: (None, 16)\n",
      "Model: \"sequential\"\n",
      "_________________________________________________________________\n",
      "Layer (type)                 Output Shape              Param #   \n",
      "=================================================================\n",
      "linear (Linear)              (None, 16)                1040      \n",
      "=================================================================\n",
      "Total params: 1,040\n",
      "Trainable params: 1,040\n",
      "Non-trainable params: 0\n",
      "_________________________________________________________________\n"
     ]
    }
   ],
   "source": [
    "tf.keras.backend.clear_session()\n",
    "\n",
    "model = models.Sequential()\n",
    "#注意该处的input_shape会被模型加工，无需使用None代表样本数量维\n",
    "model.add(Linear(units=16,input_shape=(64,)))\n",
    "print(\"model.input_shape:\",model.input_shape)\n",
    "print('model.output_shape:',model.output_shape)\n",
    "model.summary()\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}